﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.Threading;
using System.IO;
using System.Threading.Tasks;

namespace Raona.Util.Log
{
    public class FileLogger
    {
        #region Instance Fields

        private static BlockingCollection<string> logMessageQueue = new BlockingCollection<string>();
        private static string logFilePath = null;
        private static CancellationToken cancellationToken = CancellationToken.None;
        private static Task loggerTask = null;

        #endregion

        #region Class Constructor (Public)

        static FileLogger()
        {
            FileLogger.loggerTask = Task.Factory.StartNew(() => FileLogger.WriteMessages());
        }

        #endregion

        #region Class Properties (Public)

        public static string LogFilePath
        {
            get
            {
                return FileLogger.logFilePath;
            }
            set
            {
                FileLogger.logFilePath = value;
            }
        }

        public static CancellationToken CancellationToken
        {
            get
            {
                return FileLogger.cancellationToken;
            }
            set
            {
                FileLogger.cancellationToken = value;
            }
        }

        #endregion

        #region Class Methods (Public)

        public static void Log(string format, params object[] arguments)
        {
            FileLogger.logMessageQueue.Add(string.Format(format, arguments));
        }

        #endregion

        #region Class Methods (Private)

        private static void WriteMessages()
        {
            foreach (string message in logMessageQueue.GetConsumingEnumerable(FileLogger.cancellationToken))
            {
                using (FileStream file = new FileStream(FileLogger.logFilePath, FileMode.Append, FileAccess.Write))
                {
                    using (StreamWriter writer = new StreamWriter(file))
                    {
                        writer.WriteLine("[{0}] {1}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff"), message);
                    }
                }
            }
        }

        #endregion
    }
}
